import logging
import threading
from datetime import datetime
import socket
from concurrent.futures import ThreadPoolExecutor
import time
from time import perf_counter

from misc import load_list, Info

logger = logging.getLogger('app')

is_working = True

def start(check_interval):
    thread = threading.Thread(target=do_work, args=(check_interval,))
    thread.daemon = True
    thread.start()

def stop():
    global is_working
    is_working = False

def do_work(check_interval):
    # 启动 5 秒后开始工作
    time.sleep(5)
    while True:
        do_test_all()
        try:
            time.sleep(check_interval)
        except:
            break
        if not is_working:
            break


def do_test_all():
    # print(datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
    # print('----------------------------')
    data = load_list(False)
    with ThreadPoolExecutor() as executor:
        # 为每个test_one任务创建线程池
        futures = [executor.submit(test_one, item) for item in data]
        # 可以选择在这里遍历futures，根据需要处理每个任务的执行结果，比如捕获异常等，以下是示例（可按需调整）
        for future in futures:
            try:
                future.result()  # 获取任务结果，如果任务执行中抛出异常，这里会重新抛出
            except Exception as e:
                logger.error(f"任务执行出现异常: {str(e)}")
    # print('----------------------------')


def test_one(info: Info):
    alive, delay = test(info.ip, info.port)
    info.alive = alive
    info.delay = delay
    info.timestamp = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    info.dump()


def test(ip, port):
    # print('Test %s:%s...' % (ip, port))
    if isinstance(port, str):
        port = int(port)
    try:
        span = test_tcp(ip, port)
        # print('%s:%s Connected' % (ip, str(port)))
        return True, span
    except Exception as e:
        logger.warning('Connection %s:%s failed: %s' % (ip, str(port), str(e)))
        return False, -1

def test_tcp(ip, port):
    sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

    try:
        sock.settimeout(3)
        start_time = perf_counter()
        sock.connect((ip, port))
        end_time = perf_counter()
        return end_time - start_time
    finally:
        sock.shutdown(1)
